#ifndef TRADITIONAL_DETECTOR_HPP
#define TRADITIONAL_DETECTOR_HPP
#include "base_detector.hpp"
#include "hero_integrated_vision/armor.hpp"  // 包含 Light/Armor 结构体定义
#include "hero_integrated_vision/number_classifier.hpp"
#include <memory>
#include <opencv2/opencv.hpp>
#include "hero_integrated_vision/img_tools.hpp"
namespace rm_aim
{
  // 灯条参数结构体
  typedef struct 
  {
    // 灯条宽高比（width / height）
    double min_aspect_ratio;
    double max_aspect_ratio;
    // 灯条最大垂直倾斜角
    double max_vertical_tilt_angle;
  }LightParams;

  // 装甲板参数结构体
  typedef struct 
  {
    // 两个灯条长度的最小比例（短/长）
    double min_light_length_ratio;
    // 小型装甲板：灯条中心距范围
    double min_small_armor_center_dist;
    double max_small_armor_center_dist;
    // 大型装甲板：灯条中心距范围
    double min_large_armor_center_dist;
    double max_large_armor_center_dist;
    // 灯条中心连线最大水平倾斜角
    double max_horizontal_tilt_angle;
  }ArmorParams;
/**
 * @brief 传统装甲板检测器（派生自 BaseDetector）
 * @details 基于「轮廓检测→灯条筛选→装甲板匹配→数字分类」的传统流程实现检测，
 *          支持参数化配置（灯条/装甲板判断阈值），适配不同场景
 */
class TraditionalDetector : public BaseDetector
{
public:
  /**
   * @brief 构造函数（初始化基类与检测参数）
   * @param logger 日志器对象（继承自基类）
   * @param conf_threshold 置信度阈值
   * @param bin_thres 图像二值化阈值（默认180，可外部调整）
   * @param detect_color 目标阵营颜色（RED_CAMP=0 / BLUE_CAMP=1，默认RED_CAMP）
   */
  TraditionalDetector(
    const rclcpp::Logger & logger,
    const ArmorParams& armor_params,
    const LightParams& light_params,
    double conf_threshold = 0.5,
    int bin_thres = 180,
    int detect_color = RED_CAMP,  
    const std::vector<std::string> & ignore_classes= {});

  /**
   * @brief 初始化函数（加载数字分类模型，配置设备）
   * @param model_path 数字分类模型路径
   * @param device 运行设备（CPU/CUDA，默认CPU）
   * @return 初始化成功返回true，失败返回false
   */
  bool init(const std::string& model_path, const std::string& device = "CPU") override;

  /**
   * @brief 带标签的初始化函数（加载数字分类模型，配置设备）
   * @param model_path 模型路径
   * @param label_path 标签路径
   * @param device 运行设备（CPU/CUDA，默认CPU）
   * @return 初始化成功返回true，失败返回false
   */
  bool init(const std::string& model_path, const std::string& label_path, const std::string& device = "CPU");

  /**
   * @brief 核心检测接口（完整传统检测流程）
   * @param rgb_image 输入RGB图像（cv::Mat，通道顺序RGB）
   * @return 检测到的装甲板列表（含数字分类结果）
   */
  std::vector<Armor> detect(const cv::Mat& rgb_image) override;

  /**
   * @brief 检查检测器就绪状态
   * @return 初始化完成且分类器有效时返回true
   */
  bool isReady() const override;

  /**
   * @brief 绘制装甲板检测结果（装甲板边框、灯条中心点、装甲板数字、置信度）
   * @param img 输入/输出图像
   */
  void drawArmorDetectionResults(cv::Mat & img) override;

  // -------------------------- 外部配置接口 --------------------------
  /**
   * @brief 设置灯条判断参数（外部可动态调整）
   * @param params LightParams结构体（含宽高比范围、最大倾斜角）
   */
  void setLightParams(const LightParams& params) { light_params_ = params; }

  /**
   * @brief 设置装甲板判断参数（外部可动态调整）
   * @param params ArmorParams结构体（含灯条长度比、中心距范围等）
   */
  void setArmorParams(const ArmorParams& params) { armor_params_ = params; }

  /**
   * @brief 设置二值化阈值
   * @param thres 阈值（0~255，值越大二值化后白色区域越少）
   */
  void setBinaryThreshold(int thres) { binary_thres_ = thres; }

  /**
   * @brief 设置目标检测阵营
   * @param color 阵营颜色（RED_CAMP=0 / BLUE_CAMP=1）
   */
  void setDetectColor(int color) { detect_color_ = color; }

private:
  /**
   * @brief 图像预处理（RGB→灰度→二值化）
   * @param rgb_image 输入RGB图像
   * @return 二值化图像（白色为可能的灯条区域，黑色为背景）
   */
  cv::Mat preprocessImage(const cv::Mat& rgb_image);

  /**
   * @brief 灯条检测（从二值图中筛选有效灯条）
   * @param rgb_image 原始RGB图像（用于颜色判断）
   * @param binary_image 预处理后的二值图像（用于轮廓检测）
   * @return 有效灯条列表
   */
  std::vector<Light> findLights(const cv::Mat& rgb_image, const cv::Mat& binary_image);

  /**
   * @brief 灯条匹配（从灯条列表中匹配出有效装甲板）
   * @param lights 有效灯条列表
   * @return 匹配出的装甲板列表（未含数字分类结果）
   */
  std::vector<Armor> matchLights(const std::vector<Light>& lights);

  /**
   * @brief 判断单个灯条是否有效
   * @param candidate_light 候选灯条
   * @return 有效返回true，无效返回false
   */
  bool isValidLight(const Light& candidate_light);

  /**
   * @brief 判断灯条对包围盒内是否包含其他灯条（避免误判）
   * @param light1 第一个灯条
   * @param light2 第二个灯条
   * @param lights 所有有效灯条列表
   * @return 包含其他灯条返回true，否则返回false
   */
  bool isLightPairContainOtherLight(const Light& light1, const Light& light2, const std::vector<Light>& lights);

  /**
   * @brief 判断灯条对是否构成有效装甲板，并返回装甲板类型
   * @param light1 第一个灯条
   * @param light2 第二个灯条
   * @return 装甲板类型（SMALL/LARGE/INVALID）
   */
  ArmorType judgeArmorType(const Light& light1, const Light& light2);

  // -------------------------- 成员变量 --------------------------
  ArmorParams armor_params_;          // 装甲板判断参数（灯条长度比、中心距等）
  LightParams light_params_;          // 灯条判断参数（宽高比、倾斜角等）
  std::vector<Light> lights_;         // 灯条列表
  std::vector<Armor> armors_;         // 装甲板列表
  int binary_thres_;                  // 图像二值化阈值
  int detect_color_;                  // 目标阵营颜色（RED_CAMP/BLUE_CAMP）
  std::unique_ptr<NumberClassifier> classifier_;  // 数字分类器（智能指针管理生命周期）
  std::vector<std::string>  ignore_classes_;       /// 忽略的类别
};

}  // namespace rm_aim
#endif // TRADITIONAL_DETECTOR_HPP